<script setup>

import {shallowRef} from "vue";
import {myInsert, myUpdate} from "../request";
import {isNotNull} from "../util";

let parent = defineProps({

  // 表单类型：支持 insert 和 update 两种
  type: {type: String, required: false, default: 'insert'},

  /* 表单项
   *
   * label: 文案，默认表单项属性名，全类型通用
   * prop: 属性名，全类型通用
   * required: 是否必填，默认 false，全类型通用
   * span: 每个表单项的宽度占 24 分之多少，默认 24，表示独占一行，全类型通用
   * hidden: 是否隐藏，默认 false，需要占位时改为 true，全类型通用
   * placeholder: 背景字，默认 "请输入.."，icon 和 cascader 类型除外
   * disabled: 是否禁用，默认 false，icon 和 cascader 类型除外
   * readonly: 是否只读，默认 false，icon 和 cascader 类型除外
   * type: 表单项类型，支持 number, password, textarea, select, datetime, date, icon, cascader, text 9种，默认 text：
   *     type = number: 数字框
   *         min: 最小值，默认 0
   *         max: 最大值
   *         precision: 精度，默认 0
   *     type = textarea: 文本域
   *         rows: 行数，默认 8
   *         cols: 列数
   *     type = select: 下拉框
   *         options: 下拉菜单项，格式 [{ label: '', value: '' }]
   *         multiple: 是否支持多选，默认 false
   *     type = icon: ICON单选框
   *         iconSize: 按钮大小，默认 14
   *     type = cascader: 级联框
   *         options: 级联菜单项，格式 [{ label: '', value: '', children: [] }]
   *         cascaderChange: 当级联菜单发生改变时触发的函数（不带小括号）
   */
  items: {type: Array, required: true},

  // 表单规则
  rules: {type: Object, required: true},

  // API函数：表单提交时调用的API函数（不带小括号）
  api: {type: Function, required: true},

  // API参数：API请求函数参数，作为请求参数
  params: {type: Object, required: true},

  // API参数：API请求函数参数，不作为请求参数，而是有一些其它作用
  args: {type: Object, required: false, default: null},

  // 回调函数：表单提交后调用的函数（不带小括号）
  callback: {type: Function, required: false},

  // 表单宽度
  width: {type: String, required: false, default: '100%'},
});

// 表单对象
let form = shallowRef();

// 添加数据: 发送请求 + 重置表单
async function insert() {
  await myInsert({
    form: form,
    api: parent['api'],
    params: parent['params'],
    args: parent['args'],
    callback: parent['callback'],
  });
  form.value.resetFields;
}

// 修改数据: 发送请求 + 重置表单
async function update() {
  await myUpdate({
    form: form,
    api: parent['api'],
    params: parent['params'],
    args: parent['args'],
    callback: parent['callback'],
  });
  form.value.resetFields;
}

const ICONS = [
  'Plus', 'Minus', 'CirclePlus', 'Search', 'Female', 'Male', 'Aim', 'House', 'FullScreen', 'Loading',
  'Link', 'Service', 'Pointer', 'Star', 'Notification', 'Connection', 'ChatDotRound', 'Setting',
  'Clock', 'Position', 'Discount', 'Odometer', 'ChatSquare', 'ChatRound', 'ChatLineRound', 'ChatLineSquare',
  'ChatDotSquare', 'View', 'Hide', 'Unlock', 'Lock', 'RefreshRight', 'RefreshLeft', 'Refresh', 'Bell',
  'MuteNotification', 'User', 'Check', 'CircleCheck', 'Warning', 'CircleClose', 'Close', 'PieChart', 'More',
  'Compass', 'Filter', 'Switch', 'Select', 'SemiSelect', 'CloseBold', 'EditPen', 'Ed it', 'Message',
  'MessageBox', 'TurnOff', 'Finished', 'Delete', 'Crop', 'SwitchButton', 'Operation', 'Open', 'Remove',
  'ZoomOut', 'ZoomIn', 'InfoFilled', 'CircleCheckFilled', 'SuccessFilled', 'WarningFilled', 'CircleCloseFilled',
  'QuestionFilled', 'WarnTriangleFilled', 'UserFilled', 'MoreFilled', 'Tools', 'HomeFilled', 'Menu',
  'UploadFilled', 'Avatar', 'HelpFilled', 'Share', 'StarFilled', 'Comment', 'Histogram', 'Grid', 'Promotion',
  'DeleteFilled', 'RemoveFilled', 'CirclePlusFilled', 'ArrowLeft', 'ArrowUp', 'ArrowRight', 'ArrowDown',
  'ArrowLeftBold', 'ArrowUpBold', 'ArrowRightBold', 'ArrowDownBold', 'DArrowRight', 'DArrowLeft', 'Download',
  'Upload', 'Top', 'Bottom', 'Back', 'Right', 'TopRight', 'TopLeft', 'BottomRight', 'BottomLeft', 'Sort',
  'SortUp', 'SortDown', 'Rank', 'CaretLeft', 'CaretTop', 'CaretRight', 'CaretBottom', 'DCaret', 'Expand',
  'Fold', 'DocumentAdd', 'Document', 'Notebook', 'Tickets', 'Memo', 'Collection', 'Postcard', 'ScaleToOriginal',
  'SetUp', 'DocumentDelete', 'DocumentChecked', 'DataBoard', 'DataAnalysis', 'CopyDocument', 'FolderChecked',
  'Files', 'Folder', 'FolderDelete', 'FolderRemove', 'FolderOpened', 'DocumentCopy', 'DocumentRemove',
  'FolderAdd', 'FirstAidKit', 'Reading', 'DataLine', 'Management', 'Checked', 'Ticket', 'Failed', 'TrendCharts',
  'List', 'Microphone', 'Mute', 'Mic', 'VideoPause', 'VideoCamera', 'VideoPlay', 'Headset', 'Monitor', 'Film',
  'Camera', 'Picture', 'PictureRounded', 'Iphone', 'Cellphone', 'VideoCameraFilled', 'PictureFilled',
  'Platform', 'CameraFilled', 'BellFilled', 'Location', 'LocationInformation', 'DeleteLocation', 'Coordinate',
  'Bicycle', 'OfficeBuilding', 'School', 'Guide', 'AddLocation', 'MapLocation', 'Place', 'LocationFilled',
  'Van', 'Watermelon', 'Pear', 'NoSmoking', 'Smoking', 'Mug', 'GobletSquareFull', 'GobletFull', 'KnifeFork',
  'Sugar', 'Bowl', 'MilkTea', 'Lollipop', 'Coffee', 'Chicken', 'Dish', 'IceTea', 'ColdDrink', 'CoffeeCup',
  'DishDot', 'IceDrink', 'IceCream', 'Dessert', 'IceCreamSquare', 'ForkSpoon', 'IceCreamRound', 'Food',
  'HotWater', 'Grape', 'Fries', 'Apple', 'Burger', 'Goblet', 'GobletSquare', 'Orange', 'Cherry', 'Printer',
  'Calendar', 'CreditCard', 'Box', 'Money', 'Refrigerator', 'Cpu', 'Football', 'Brush', 'Suitcase',
  'SuitcaseLine', 'Umbrella', 'AlarmClock', 'Medal', 'GoldMedal', 'Present', 'Mouse', 'Watch', 'QuartzWatch',
  'Magnet', 'Help', 'Soccer', 'ToiletPaper', 'ReadingLamp', 'Paperclip', 'MagicStick', 'Basketball',
  'Baseball', 'Coin', 'Goods', 'Sell', 'SoldOut', 'Key', 'ShoppingCart', 'ShoppingCartFull', 'ShoppingTrolley',
  'Phone', 'Scissor', 'Handbag', 'ShoppingBag', 'Trophy', 'TrophyBase', 'Stopwatch', 'Timer', 'CollectionTag',
  'TakeawayBox', 'PriceTag', 'Wallet', 'Opportunity', 'PhoneFilled', 'WalletFilled', 'GoodsFilled', 'Flag',
  'BrushFilled', 'Briefcase', 'Stamp', 'Sunrise', 'Sunny', 'Ship', 'MostlyCloudy', 'PartlyCloudy', 'Sunset',
  'Drizzling', 'Pouring', 'Cloudy', 'Moon', 'MoonNight', 'Lightning', 'ChromeFilled', 'Eleme', 'ElemeFilled',
  'ElementPlus', 'Shop', 'SwitchFilled', 'WindPower'
];
</script>

<template>
  <el-form class="my-form"
           ref="form"
           status-icon
           label-width="auto"
           size="small"
           :model="params"
           :rules="rules"
           :style="{'width': width}">
    <el-row :gutter="20">
      <el-col class="layout-col"
              v-for="item in items"
              :key="item"
              :span="isNotNull(item['span']) ? item['span'] : 24">
        <el-form-item class="form-item"
                      :label="isNotNull(item['label']) ? item['label'] : item['prop']"
                      :prop="item['prop']"
                      :required="item['required']"
                      v-show="!item['hidden']">
          <!--数字框-->
          <el-input-number v-if="item['type'] === 'number'"
                           clearable
                           v-model="params[item['prop']]"
                           :min="isNotNull(item['min']) ? item['min'] : 0"
                           :max="item['max']"
                           :precision="isNotNull(item['precision']) ? item['precision'] : 0"
                           :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                           :disabled="item['disabled']"
                           :readonly="item['readonly']"/>
          <!--密码框-->
          <el-input v-else-if="item['type'] === 'password'"
                    clearable
                    show-password
                    v-model="params[item['prop']]"
                    :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                    :disabled="item['disabled']"
                    :readonly="item['readonly']"/>
          <!--文本域-->
          <el-input v-else-if="item['type'] === 'textarea'"
                    type="textarea"
                    clearable
                    resize="none"
                    v-model="params[item['prop']]"
                    :rows="isNotNull(item['rows']) ? item['rows'] : 8"
                    :cols="item['cols']"
                    :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                    :disabled="item['disabled']"
                    :readonly="item['readonly']"/>
          <!--下拉框-->
          <el-select v-else-if="item['type'] === 'select'"
                     clearable
                     filterable
                     :multiple="item['multiple']"
                     v-model="params[item['prop']]"
                     :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                     :disabled="item['disabled']"
                     :readonly="item['readonly']">
            <el-option class="select-item"
                       v-for="option in item['options']"
                       :key="option"
                       :label="option['label']"
                       :value="option['value']"/>
          </el-select>
          <!--时间框-->
          <el-date-picker v-else-if="item['type'] === 'datetime'"
                          type="datetime"
                          clearable
                          v-model="params[item['prop']]"
                          format="YYYY-MM-DD HH:mm"
                          value-format="YYYY-MM-DDTHH:mm:ss"
                          :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                          :disabled="item['disabled']"
                          :readonly="item['readonly']"/>
          <!--日期框-->
          <el-date-picker v-else-if="item['type'] === 'date'"
                          type="date"
                          clearable
                          v-model="params[item['prop']]"
                          format="YYYY-MM-DD"
                          value-format="YYYY-MM-DD"
                          :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                          :disabled="item['disabled']"
                          :readonly="item['readonly']"/>
          <!--ICON单选框-->
          <el-radio-group v-else-if="item['type'] === 'icon'"
                          class="icon-list"
                          size="small"
                          v-model="params[item['prop']]">
            <el-radio-button class="icon-item"
                             v-for="icon in ICONS"
                             :key="icon"
                             :label="icon">
              <template #default>
                <el-icon :size="isNotNull(item['iconSize']) ? item['iconSize'] : 14">
                  <component :is="icon"/>
                </el-icon>
              </template>
            </el-radio-button>
          </el-radio-group>
          <!--级联框-->
          <el-cascader v-else-if="item['type'] === 'cascader'"
                       v-model="params[item['prop']]"
                       :options="item['options']"
                       :props="{expandTrigger: 'hover'}"
                       @change="params[item['cascaderChange']]"
                       style="width: 100%;"/>
          <!--文本框-->
          <el-input v-else
                    clearable
                    v-model="params[item['prop']]"
                    :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                    :disabled="item['disabled']"
                    :readonly="item['readonly']"/>
        </el-form-item>
      </el-col>
    </el-row>
    <el-form-item class="btn-item">
      <el-button class="insert-btn"
                 v-if="type === 'insert'"
                 type="primary"
                 @click="insert">
        确认添加
      </el-button>
      <el-button class="update-btn"
                 v-else-if="type === 'update'"
                 type="primary"
                 @click="update">
        确认修改
      </el-button>
    </el-form-item>
  </el-form>
</template>

<style scoped lang="scss">
.my-form {
  .el-input-number, .el-button {
    width: 100%; // 宽度
  }
}

:deep(.el-date-editor) {
  --el-date-editor-width: 100%; // 宽度
}

.icon-list {
  margin-left: -2px; // 左外边距
  max-height: 160px; // 最大高
  overflow-y: scroll; // Y滚动
  .el-radio-button {
    margin-bottom: 5px; // 下外边距
  }
}

/* 取消首尾按钮的圆角 */
:deep(.el-radio-button:first-child .el-radio-button__inner),
:deep(.el-radio-button:last-child .el-radio-button__inner) {
  border-radius: 0; // 圆角
}

/* 修改单选按钮样式 */
:deep(.el-radio-button--small .el-radio-button__inner) {
  border-left: 1px solid #7e7e7e; // 左边框
  margin: 0 2px; // 左右外边距
}
</style>